#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/input.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdbool.h>
#include "inc/game2048.h"
#include"inc/app.h"
#include "lvgl/lvgl.h"
#include "lvgl/demos/lv_demos.h"
#include <stdio.h>
//extern const lv_font_t lv_mygec_font;
/*
    rand_2_or_4：分别以90%、10%的概率随机生成2、4
    返回值:
        2或4
*/
//lv_obj_t *scr;
int rand_2_or_4()
{
    if(rand()%10==0)
    {
        return 4;
    }
    else
    {
        return 2;
    }
}



/*
    rand_empty：从二维数组中选择一个空位
    @p：指向二维数组地址
    返回值:
        有空位返回空位地址，无空位返回null
*/
int *rand_empty(int **p)
{
    int a[16][2];
    int count = 0;
    for(int i=0;i<4;i++)
    {
        for(int j=0;j<4;j++)
        {
            if(p[i][j]==0)
            {
                a[count][0]=i;
                a[count][1]=j;
                count++;
            }
        }
    }
    if(count==0) return NULL;

    int index = rand() % count;
    int x=a[index][0];
    int y=a[index][1];
    
    return &(p[x][y]);
}



/*
    game_start：开始游戏,随机选一个格子放数据
    返回值:
        指向二维数组的指针
*/
int **game_start()
{   
    //申请一个二级指针
    int **p=malloc(4*sizeof(int *));
    if(p==NULL) return NULL;

    for(int i=0;i<4;i++){
        p[i]=malloc(4*sizeof(int));
        if(p[i]==NULL)
        {
            //错误处理，释放空间
            for(int j=0;j<i;j++)
            {
                free(p[j]);
            }
            free(p);
            return NULL;
        }

        for(int j=0;j<4;j++)
        {
            p[i][j]=0;
        }

    }

    int *q=rand_empty(p);
    *q=rand_2_or_4();

    return p;
}



/*
    game_is_over：判断游戏是否结束
    @p：指向二维数组地址
    返回值:
        游戏结束返回false，游戏未结束返回true
*/
bool game_is_over(int **p)
{
    //只要还有空，直接返回true
    if(rand_empty(p)!=NULL)
    {
        return true;
    }

    //没有空，判断相邻是否有相同
    for(int i=0;i<3;i++)
    {
        //最后一行和最后一列的判断
        if(p[i][3]==p[i+1][3]||p[3][i]==p[3][i+1])
        {
            return true;
        }

        //其他位置的判断
        for(int j=0;j<3;j++)
        {
            if(p[i][j]==p[i+1][j]||p[i][j]==p[i][j+1])
            {
                return true;
            }
        }
    }

    return false;

}


/*
    up_synthesis:向上合成
    @x:当前判断的格子的行数
    @y:当前判断的格子的列数
    @p:二维数组的地址
*/
void up_synthesis(int x,int y,int **p)
{
    //如果p[x][y]=0,结束
    if(p[x][y]==0)  return;

    //如果不是0,先移到当前列行数最低的位置,x=0时不用动
    while(x!=0&&p[x-1][y]==0)
    {
        p[x-1][y]=p[x][y];
        p[x][y]=0;
        x=x-1;
    }

    //注意传过来的x最多为四行里的第三行，即x<3
    for(int i=x+1;i<4;i++)          
    {
        //寻找同一列的第一个非0值,相同就合成,不同不用管，因为up_synthesis会对二维数组中每一个位置使用
        if(p[x][y]==p[i][y])
        {
            p[x][y]=2*p[x][y];
            p[i][y]=0;
            score+=p[x][y];
            return;
        }
        else if(p[x][y]!=p[i][y]&&p[i][y]!=0)
        {
            return;
        }    
    }
}


/*
    down_synthesis:向下合成
    @x:当前判断的格子的行数
    @y:当前判断的格子的列数
    @p:二维数组的地址
*/
void down_synthesis(int x,int y,int **p)
{
    //如果p[x][y]=0,结束
    if(p[x][y]==0)  return;

    //如果不是0,先移到当前列行数最高的位置,x=3时不用动
    while(x!=3&&p[x+1][y]==0)
    {
        p[x+1][y]=p[x][y];
        p[x][y]=0;
        x=x+1;
    }

    //做完如果x为0，则无任何改变
    //不用写，i>=0已经作出判断
    //if(x==0) return;

    //若x！=0
    for(int i=x-1;i>=0;i--)          
    {
        //寻找同一列的第一个非0值,相同就合成,不同不用管，因为up_synthesis会对二维数组中每一个位置使用
        if(p[x][y]==p[i][y])
        {
            p[x][y]=2*p[x][y];
            p[i][y]=0;
            score+=p[x][y];
            return;
        }
        else if(p[x][y]!=p[i][y]&&p[i][y]!=0)
        {
            return;
        }    
    }
}


/*
    left_synthesis:向左合成
    @x:当前判断的格子的行数
    @y:当前判断的格子的列数
    @p:二维数组的地址
*/
void left_synthesis(int x,int y,int **p)
{
    //如果p[x][y]=0,结束
    if(p[x][y]==0)  return;

    //如果不是0,先移到当前行列数最低的空位,y=0时不用动
    while(y!=0&&p[x][y-1]==0)
    {
        p[x][y-1]=p[x][y];
        p[x][y]=0;
        y=y-1;
    }

    //遍历合成
    for(int i=y+1;i<4;i++)          
    {
        //寻找同一行右边的第一个非0值,相同就合成,不同不用管，因为left_synthesis会对二维数组中每一个位置使用
        if(p[x][y]==p[x][i])
        {
            p[x][y]=2*p[x][y];
            p[x][i]=0;
            score+=p[x][y];
            return;
        }
        else if(p[x][y]!=p[x][i]&&p[x][i]!=0)
        {
            return;
        }    
    }
}


/*
    right_synthesis:向右合成
    @x:当前判断的格子的行数
    @y:当前判断的格子的列数
    @p:二维数组的地址
*/
void right_synthesis(int x,int y,int **p)
{
    //如果p[x][y]=0,结束
    if(p[x][y]==0)  return;

    //如果不是0,先移到当前行列数最高的空位,y=3时不用动
    while(y!=3&&p[x][y+1]==0)
    {
        p[x][y+1]=p[x][y];
        p[x][y]=0;
        y=y+1;
    }

    //遍历合成
    for(int i=y-1;i>=0;i--)          
    {
        //寻找同一行左边的第一个非0值,相同就合成,不同不用管，因为right_synthesis会对二维数组中每一个位置使用
        if(p[x][y]==p[x][i])
        {
            p[x][y]=2*p[x][y];
            p[x][i]=0;
            score+=p[x][y];
            return;
        }
        else if(p[x][y]!=p[x][i]&&p[x][i]!=0)
        {
            return;
        }    
    }
}


/*
    block_synthesis：方块合成
    @ev:保存滑动方向的结构体
    @p:指向二维数组地址
    返回值：
        修改后的数组地址
*/
int **block_synthesis(event *ev,int **p)
{
    if(ev->way==UP)
    {
        //向上划，向上合成，方块从0行遍历到3行
        for(int i=0;i<4;i++)
        {
            for(int j=0;j<4;j++)
            {
                up_synthesis(i,j,p);
            }
        }
        return p;
    }
    else if(ev->way==DOWN)
    {
        //向下划，向下合成，方块从3行遍历到0行
        for(int i=3;i>=0;i--)
        {
            for(int j=0;j<4;j++)
            {
                down_synthesis(i,j,p);
            }
        }
        return p;
    }
    else if(ev->way==LEFT)
    {
        //向左划，向左合成，方块从0列遍历到3行
        for(int i=0;i<4;i++)
        {
            for(int j=0;j<4;j++)
            {
                left_synthesis(j,i,p);
            }
        }
        return p;
    }
    else if(ev->way==RIGHT)
    {
        //向右划，向右合成，方块从3列遍历到0行
        for(int i=3;i>=0;i--)
        {
            for(int j=0;j<4;j++)
            {
                right_synthesis(j,i,p);
            }
        }
        return p;
    }  
}


/*
    game_save：存档
    @p:指向二维数组地址
*/
void game_save(int **p,int score)
{
    FILE *f=fopen("/tzh/save.txt","w");
    if(f==NULL){
        perror("fopen");
        return ;
    }

    fprintf(f,"%d\n",score);

    int i=0;
    while(i<4){
        //以规定的格式写入文件
        fprintf(f,"%d %d %d %d\n",p[i][0],p[i][1],p[i][2],p[i][3]);
        i++;
    }

    fclose(f);

}


/*
    game_read：读档
*/
void game_read(int **p,int *score)
{
    char buff[1024]={0};

    FILE *f=fopen("/tzh/save.txt","r");
    if(f==NULL)
    {
        perror("fopen");
        return ;
    }

    if(fgets(buff,sizeof(buff),f)){
        sscanf(buff,"%d",score);
    }

    for (int i = 0; i < 4; i++) 
    {
        if (fgets(buff, sizeof(buff), f) == NULL) 
        {
            fprintf(stderr, "读取文件时发生错误(行 %d)\n", i);
            break;
        }

        int a, b, c, d;
        if (sscanf(buff, "%d %d %d %d", &a, &b, &c, &d) != 4)
        {
            fprintf(stderr, "文件格式错误(行 %d)\n", i);
            break;
        }

        // 保存到二维数组 p[i][0~3]
        p[i][0] = a;
        p[i][1] = b;
        p[i][2] = c;
        p[i][3] = d;
    }

    fclose(f);
}



static GameUI ui_instance;
lv_obj_t *fullscreen_img = NULL;

/*
    get_tile_color：根据数字获取对应的背景色
    @value：数字
    返回值：
        相应的颜色
*/
lv_color_t get_tile_color(int value) 
{
    switch (value) 
    {
        case 2:    return lv_color_hex(0xeee4da);
        case 4:    return lv_color_hex(0xede0c8);
        case 8:    return lv_color_hex(0xf2b179);
        case 16:   return lv_color_hex(0xf59563);
        case 32:   return lv_color_hex(0xf67c5f);
        case 64:   return lv_color_hex(0xf65e3b);
        case 128:  return lv_color_hex(0xedcf72);
        case 256:  return lv_color_hex(0xedcc61);
        case 512:  return lv_color_hex(0xedc850);
        case 1024: return lv_color_hex(0xedc53f);
        case 2048: return lv_color_hex(0xedc22e);
        default:   return lv_color_hex(0x3c3a32);
    }
}


void button_box(lv_event_t * e)
{
    execlp("./main","main",NULL);
    //
   // lv_obj_del(scr);
   // scr=NULL;
// lv_obj_add_flag(scr,LV_OBJ_FLAG_HIDDEN);
    game2_ui_requested=1;
  //  lv_obj_remove_flag(app_container, LV_OBJ_FLAG_HIDDEN);
}



/*
    print_get_way_cb:获取网格区域滑动方向
*/
void print_get_way_cb(lv_event_t *e)
{
    //必须为static！！！
    static lv_point_t p1; // 按下位置
    lv_point_t p2;        // 抬起位置
    lv_event_code_t code = lv_event_get_code(e); // 获取事件代码
    
    if(code==LV_EVENT_PRESSED)      //刚刚按下
    {
        lv_indev_get_point(lv_indev_active(),&p1);     //获取输入设备的进入坐标
    }
    else if(code==LV_EVENT_RELEASED)    //松开
    {
        lv_indev_get_point(lv_indev_active(),&p2);     //获取输入设备的离开坐标

        if(abs(p2.x-p1.x)<=50 && abs(p2.y-p1.y)<=50)  //点击
        {
            ev.x=p1.x;
            ev.y=p1.y;
            ev.flag=1;
            ev.way=OTH;
        }
        else
        {
            if(abs(p2.y-p1.y)>abs(p2.x-p1.x))
            {
                if(p2.y>p1.y)
                {
                    printf("DOWN\n");
                    ev.way=DOWN;
                }
                else
                {
                    printf("UO\n");
                    ev.way=UP;
                }
            }
            else
            {
                if(p2.x>p1.x)
                {
                    printf("RIGHT\n");
                    ev.way=RIGHT;
                }
                else
                {
                    printf("LEFT\n");
                    ev.way=LEFT;
                }
            }
            ev.flag=1;
        }
    }
}

/*
    rst_cb:重开按钮的回调函数
*/
void rst_cb(lv_event_t *e)
{
    p=game_start();

    if(ev.flag2==1)
    {
        for(int i=0;i<4;i++)
        {
            for(int j=0;j<4;j++)
            {
                p[i][j]=0;
            }
        }
    }

    score=0;
    ev.flag2=0;
    ui_update(p);
}



/*
    ui_start：开始菜单
*/
void ui_start()
{
    //获取当前活动的屏幕对象
    lv_obj_t *start=lv_obj_create(lv_screen_active());

    //显示图片
    show_bmp_fullscreen("A:/tzh/2048.bmp",800,480);
    lv_timer_handler(); 

}



/*
    ui_init：初始化游戏ui界面，包括4*4网格、分数栏、重开按钮
*/
void ui_init()
{
    //获取当前活动的屏幕对象
    lv_obj_t *scr=lv_screen_active();
    if(!scr) return;

    //根据屏幕对象创建网格对象480*480,从左上角开始
    ui_instance.grid=lv_obj_create(scr);
    lv_obj_set_size(ui_instance.grid,480,480);
    lv_obj_set_pos(ui_instance.grid,0,0);

    //设置网格样式
    static lv_style_t style_grid;
    lv_style_init(&style_grid);
    lv_style_set_bg_color(&style_grid,lv_color_hex(0xbbada0));
    lv_style_set_radius(&style_grid, 10);
    lv_style_set_pad_all(&style_grid, GRID_PADDING);
    lv_obj_add_style(ui_instance.grid, &style_grid, LV_STATE_DEFAULT);

    //计算格子位置
    const int available_size = 480 - 2*GRID_PADDING;
    const int tile_with_gap = TILE_SIZE + TILE_GAP;
    const int offset = (available_size - GRID_SIZE*tile_with_gap + TILE_GAP)/2;
    
    //创建16个格子
    for (int i = 0; i < GRID_SIZE; i++) {
        for (int j = 0; j < GRID_SIZE; j++) {
            ui_instance.tiles[i][j] = lv_obj_create(ui_instance.grid);
            //设置格子的大小和位置
            lv_obj_set_size(ui_instance.tiles[i][j], TILE_SIZE, TILE_SIZE);
            lv_obj_set_pos(ui_instance.tiles[i][j], 
                          offset + j * tile_with_gap, 
                          offset + i * tile_with_gap);
            
            // 设置格子基础样式
            static lv_style_t style_tile;
            lv_style_init(&style_tile);
            lv_style_set_bg_color(&style_tile, lv_color_hex(0xcdc1b4));
            lv_style_set_radius(&style_tile, 5);
            lv_style_set_text_color(&style_tile, lv_color_hex(0x776e65));
            lv_style_set_text_font(&style_tile, &lv_font_montserrat_28); // 增大字体
            lv_style_set_text_align(&style_tile, LV_TEXT_ALIGN_CENTER);
            lv_obj_add_style(ui_instance.tiles[i][j], &style_tile, LV_STATE_DEFAULT);
            
            // 创建标签用于显示数字
            lv_obj_t *label = lv_label_create(ui_instance.tiles[i][j]);
            lv_label_set_text(label, "");
            lv_obj_center(label);
            // 关键设置：禁用tile的事件处理
            lv_obj_clear_flag(ui_instance.tiles[i][j], LV_OBJ_FLAG_CLICKABLE);
            lv_obj_add_flag(ui_instance.tiles[i][j], LV_OBJ_FLAG_EVENT_BUBBLE);
        }
    }

    //右半边屏幕的上方设置窗口显示分数
    ui_instance.score_win = lv_obj_create(scr);
    lv_obj_set_size(ui_instance.score_win, 220, 100);  // 设置窗口大小
    lv_obj_set_pos(ui_instance.score_win, 530, 50);    // 设置位置
    lv_obj_set_style_border_width(ui_instance.score_win, 3, 0);  // 边框宽度
    lv_obj_set_style_border_color(ui_instance.score_win, lv_color_hex(0x3498db), 0); // 蓝色边框
    lv_obj_set_style_bg_color(ui_instance.score_win, lv_color_hex(0xffffff), 0); // 白色背景
    lv_obj_set_style_radius(ui_instance.score_win, 10, 0); // 圆角半径

    // 创建分数标签
    ui_instance.score_label = lv_label_create(ui_instance.score_win);
    lv_label_set_text(ui_instance.score_label, "0"); // 初始分数
    lv_obj_center(ui_instance.score_label); // 居中显示

    // 设置分数文本样式
    lv_obj_set_style_text_font(ui_instance.score_label, &lv_font_montserrat_20, 0); // 大号字体
    lv_obj_set_style_text_color(ui_instance.score_label, lv_color_hex(0x2c3e50), 0); // 深蓝色文字

    



    //右半边屏幕的中部设置重开按钮
    ui_instance.rst_win = lv_obj_create(scr);
    lv_obj_set_size(ui_instance.rst_win, 220, 100);  // 设置窗口大小
    lv_obj_set_pos(ui_instance.rst_win, 530, 190);    // 设置位置
    lv_obj_set_style_border_width(ui_instance.rst_win, 3, 0);  // 边框宽度
    lv_obj_set_style_border_color(ui_instance.rst_win, lv_color_hex(0x3498db), 0); // 蓝色边框
    lv_obj_set_style_bg_color(ui_instance.rst_win, lv_color_hex(0xFFD60A), 0); // 
    lv_obj_set_style_radius(ui_instance.rst_win, 10, 0); // 圆角半径

    // 创建标签
    lv_obj_t *rst_label = lv_label_create(ui_instance.rst_win);
    lv_label_set_text(rst_label, "restart"); 
    lv_obj_center(rst_label); // 居中显示
    //lv_obj_set_style_text_font(rst_label, &lv_mygec_font, LV_PART_MAIN);
    // 设置文本样式
    lv_obj_set_style_text_font(rst_label, &lv_font_montserrat_20, 0); // 大号字体
    lv_obj_set_style_text_color(rst_label, lv_color_hex(0x2c3e50), 0); // 深蓝色文字




    //右半边屏幕的下方设置退出按钮
    ui_instance.exit_win = lv_obj_create(scr);
    lv_obj_set_size(ui_instance.exit_win, 220, 100);  // 设置窗口大小
    lv_obj_set_pos(ui_instance.exit_win, 530, 330);    // 设置位置
    lv_obj_set_style_border_width(ui_instance.exit_win, 3, 0);  // 边框宽度
    lv_obj_set_style_border_color(ui_instance.exit_win, lv_color_hex(0x3498db), 0); // 蓝色边框
    lv_obj_set_style_bg_color(ui_instance.exit_win, lv_color_hex(0xFF6F61), 0); // 
    lv_obj_set_style_radius(ui_instance.exit_win, 10, 0); // 圆角半径

    // 创建标签
    lv_obj_t *exit_label2 = lv_label_create(ui_instance.exit_win);
    lv_label_set_text(exit_label2, "exit"); 
    lv_obj_center(exit_label2); // 居中显示
    //lv_obj_set_style_text_font(exit_label, &lv_mygec_font, LV_PART_MAIN);
    // 设置文本样式
    lv_obj_set_style_text_font(exit_label2, &lv_font_montserrat_20, 0); // 大号字体
    lv_obj_set_style_text_color(exit_label2, lv_color_hex(0x2c3e50), 0); // 深蓝色文字




    //可能和我的触摸屏检测冲突了
    ev.flag=0;
    lv_obj_add_event_cb(ui_instance.grid, print_get_way_cb, LV_EVENT_ALL, NULL);
    lv_obj_add_event_cb(ui_instance.rst_win, rst_cb, LV_EVENT_SHORT_CLICKED, NULL);
    lv_obj_add_event_cb(ui_instance.exit_win, button_box, LV_EVENT_SHORT_CLICKED, NULL);
}

/*
    ui_update:刷新显示
    @p:二维数组指针
*/

void ui_update(int **p)
{
    printf("%d\n",ev.way);
    for(int i=0;i<4;i++)
    {
        for(int j=0;j<4;j++)
        {
            printf("%d ",p[i][j]);
        }
        printf("\n");
    }
    printf("\n");

    // 确保UI已初始化
    if (ui_instance.grid == NULL) return;

    // 更新游戏格子
    for (int i = 0; i < GRID_SIZE; i++) {
        for (int j = 0; j < GRID_SIZE; j++) {
            lv_obj_t *tile = ui_instance.tiles[i][j];
            lv_obj_t *label = lv_obj_get_child(tile, 0);
            int value = p[i][j];
            
            if (value != 0) {
                char num_str[6];
                snprintf(num_str, sizeof(num_str), "%d", value);
                lv_label_set_text(label, num_str);
                lv_obj_set_style_bg_color(tile, get_tile_color(value), 0);
                
                const lv_font_t *font = (value < 100) ? &lv_font_montserrat_28 :
                                      (value < 1000) ? &lv_font_montserrat_22 :
                                      &lv_font_montserrat_18;
                lv_obj_set_style_text_font(label, font, 0);
            } else {
                lv_label_set_text(label, "");
                lv_obj_set_style_bg_color(tile, lv_color_hex(0xcdc1b4), 0);
            }
        }
    }  

    //更新分数标签
    char str[9];
    snprintf(str, sizeof(str), "%d", score);
    lv_label_set_text(ui_instance.score_label, str);

    game_save(p,score);

    //确保刷新！！！！！！！！！！
   // lv_refr_now(NULL);
}



/*
    show_bmp_fullscreen:显示图片
    @bmp_path：路径
    @w
    @h
*/
void show_bmp_fullscreen(const char *bmp_path,int w,int h) {
    // 如果已有图片，先删除
    if (fullscreen_img != NULL) {
        lv_obj_del(fullscreen_img);
        fullscreen_img = NULL;
    }

    // 创建全屏图片
    fullscreen_img = lv_img_create(lv_scr_act());  // 直接放在屏幕上
    lv_img_set_src(fullscreen_img, bmp_path);      // 加载 BMP
    lv_obj_set_size(fullscreen_img, w, h);  // 全屏
    lv_obj_set_pos(fullscreen_img, 0, 0);      
}



/*
    hide_bmp_fullscreen：隐藏图片
*/
void hide_bmp_fullscreen() {
    if (fullscreen_img != NULL) {
        lv_obj_del(fullscreen_img);  // 彻底删除
        fullscreen_img = NULL;       
    }
}


